package raytracing;

import java.awt.Dimension;

import structs.Matrix;
import structs.Vector2;
import structs.Vector3;

public class PerspectiveCamera implements ICamera {

	private Vector3 e;
	private Vector3 u;
	private Vector3 v;
	private Vector3 w;
	float l;
	float r;
	float t;
	float b;
	// private float viewplaneWidth;
	// private float viewplaneHeight;
	private float viewplaneDistance;
	private float pixelDimX;
	private float pixelDimY;

	public PerspectiveCamera() {
		u = new Vector3(0,0,1);
		v = new Vector3(0, 1, 0);
		w = new Vector3(-1,0,0);
		setWorldMatrix(Matrix.identity());
		
		r = 25;
		l = -r;
		t = 25;
		b = -t;
		viewplaneDistance = 5;
		pixelDimX = 100;
		pixelDimY = 100;
	}

	@Override
	public Ray getRay(int row, int column) {
		if (column > pixelDimX || row > pixelDimY)
			throw new IllegalArgumentException();

		float uf = (float) (l + (r - l) * (column + 0.5) / pixelDimX);
		float vf = (float) (b + (t - b) * (row + 0.5) / pixelDimY);
		
		Ray ray = new Ray();
		ray.Origin = e;
		Vector3 v1 = w.multiply(-viewplaneDistance);
		Vector3 v2 = u.multiply(uf);
		Vector3 v3 = v.multiply(vf);
		ray.Direction = (v1.plus(v2)).plus(v3);
		ray.Direction.normalize();
		return ray;
	}

	@Override
	public void setWorldMatrix(Matrix m) {
		e = m.getTranslation();
		Matrix r = m.getRotation();
		u.transform(r);
		v.transform(r);
		w.transform(r);
	}

	@Override
	public void setViewplaneDimensions(Vector2 dim) {
		// viewplaneHeight = dim.Y;
		// viewplaneWidth = dim.X;
		r = dim.X / 2;
		l = -r;
		t = dim.Y / 2;
		b = -t;
	}

	@Override
	public void setPixelDimensions(Dimension dim) {
		pixelDimX = dim.width;
		pixelDimY = dim.height;
		setViewplaneDimensions(new Vector2(2*r, 2*t*dim.height/dim.width));
	}

	public void setViewplaneDistance(float focalLength) {
		viewplaneDistance = focalLength;
	}

}
